﻿using System.Collections.Generic;
using System.Linq;
using System.Security.Principal;
using System.Windows;

namespace UltimateNavigationFramework.Authorisation
{
    public class NavigationAuthorisation : DependencyObject
    {
        /// <summary>
        /// Gets or sets, in a comma-separated list, the set of roles to be denied.
        /// </summary>
        public static readonly DependencyProperty RolesProperty =
            DependencyProperty.Register("Roles", typeof(string), typeof(NavigationAuthorisation), new PropertyMetadata(""));

        /// <summary>
        /// Gets or sets, in a comma-separated list, the set of users to denied.  "?" indicates anonymous users will be denied.
        /// "*" indicates that all users will be denied.
        /// </summary>
        public static readonly DependencyProperty UsersProperty =
            DependencyProperty.Register("Users", typeof(string), typeof(NavigationAuthorisation), new PropertyMetadata(""));

        /// <summary>
        /// Gets or sets, in a comma-separated list, the set of roles to be denied.
        /// </summary>
        public string Roles
        {
            get { return (string)this.GetValue(RolesProperty); }
            set { this.SetValue(RolesProperty, value); }
        }

        /// <summary>
        /// Gets or sets, in a comma-separated list, the set of users to denied.  "?" indicates anonymous users will be denied.
        /// "*" indicates that all users will be denied.
        /// </summary>
        public string Users
        {
            get { return (string)this.GetValue(UsersProperty); }
            set { this.SetValue(UsersProperty, value); }
        }

        /// <summary>
        /// Determines if it has any roles match from the principal object
        /// </summary>
        /// <param name="roles"></param>
        /// <param name="principal"></param>
        /// <returns></returns>
        protected static bool HasAnyRole(string roles, IPrincipal principal)
        {
            if (principal == null)
                return false;

            if (roles.Contains("*")) // Accepts all
                return true;

            IEnumerable<string> roleList = from r in roles.Split(',')
                                           select r.Trim();

            return roleList.Any(principal.IsInRole);
        }

        /// <summary>
        /// Determines if it has any user match in the principal identity
        /// </summary>
        /// <param name="users"></param>
        /// <param name="principal"></param>
        /// <returns></returns>
        protected static bool HasUser(string users, IPrincipal principal)
        {
            IEnumerable<string> userList = from u in users.Split(',')
                                           select u.Trim();

            if (principal == null || principal.Identity == null || !principal.Identity.IsAuthenticated)
                return userList.Contains("?") || userList.Contains("*");

            return userList.Contains("*") || userList.Contains(principal.Identity.Name);
        }
    }
}
